package com.shunda.ysdgj.manager.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import com.shunda.ysdgj.common.exception.CustomException;
import com.shunda.ysdgj.manager.service.UploadService;
import com.shunda.ysdgj.model.dto.FileDto;
import com.shunda.ysdgj.model.vo.FileVo;
import com.shunda.ysdgj.model.vo.ResultCodeEnum;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class UploadServiceImpl implements UploadService {

    private final MinioClient minioClient;

    @Override
    public FileVo uploadPicture(String usage, MultipartFile file) {
        String contentType = file.getContentType();
        Map<String, String> mimeTypeMap = getMimeTypeMap();
        if (!mimeTypeMap.containsKey(contentType)) {
            throw new CustomException(ResultCodeEnum.UPLOAD_PICTURE_ERROR);
        }
        String url = upload(usage, file);
        FileVo fileVo = new FileVo();
        fileVo.setUrl(url);
        fileVo.setName(url);
        return fileVo;
    }

    @Override
    public String upload(String usage, MultipartFile file) {
        String bucketName = getBucketName();
        LocalDateTime now = LocalDateTime.now();
        String dateStr = LocalDateTimeUtil.format(now, "yyyyMMdd");
        String dateTimeStr = LocalDateTimeUtil.format(now, "yyyyMMddHHmmss");
        String randStr = IdUtil.simpleUUID();
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new CustomException(ResultCodeEnum.UPLOAD_ERROR);
        }
        String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        String fileName = String.format("%s/%s/%s%s.%s", usage, dateStr, dateTimeStr, randStr, extension);
        try {
            minioClient.putObject(
                    PutObjectArgs
                            .builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .build()
            );
        } catch (Exception e) {
            throw new CustomException(ResultCodeEnum.UPLOAD_ERROR);
        }

        return fileName;
    }

    public void removeFiles(FileDto fileDto) {
        List<String> fileNames = fileDto.getFileNames();
        for (String fileName : fileNames) {
            remove(fileName);
        }
    }

    public void remove(String fileName) {
        String bucketName = getBucketName();
        try {
            minioClient.removeObject(
                    RemoveObjectArgs
                            .builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
        } catch (Exception e) {
            throw new CustomException(ResultCodeEnum.FAIL);
        }
    }

    private String getBucketName() {
        return "ysdgj-manager";
    }

    private Map<String, String> getMimeTypeMap() {
        Map<String, String> mimeTypeMap = new HashMap<>();
        mimeTypeMap.put("image/jpeg", "jpeg");
        mimeTypeMap.put("image/png", "png");
        mimeTypeMap.put("image/gif", "gif");
        mimeTypeMap.put("image/avif", "avif");
        return mimeTypeMap;
    }
}
